package pl.veneo.wigprofit.view.elements {
	import pl.veneo.wigprofit.model.Configuration;
	import pl.veneo.wigprofit.model.PeriodData;
	import pl.veneo.wigprofit.tools.TimeSpan;

	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;

	/**
	 * @author Tomasz Swierszcz, fiodorkrk@gmail.com
	 */
	public class ChartScales extends Sprite {
		private const GRIDWIDTH : int = 60;
		private var _width : Number;
		private var _height : Number;
		private var _percents : Sprite;
		private var _indexes : Sprite;
		private var _dates : Sprite;
		private var _period : PeriodData;
		private var _daysCount : int;

		public function ChartScales(width : Number, height : Number) {
			_height = height;
			_width = width;

			graphics.lineStyle(0, Configuration.getInstance().strongColor);
			var posY : Number;

			for (var i : int = 0; i < 10; i++) {
				posY = _height / 10 * i;
				graphics.moveTo(0, posY);
				graphics.lineTo(_width, posY);
			}

			graphics.lineStyle(1, Configuration.getInstance().lightColor);
			graphics.moveTo(0, 0);
			graphics.lineTo(0, _height);
			graphics.lineTo(_width, _height);
			graphics.lineTo(_width, 0);
		}

		public function draw(period : PeriodData) : void {
			_period = period;
			_daysCount = TimeSpan.fromDates(_period.startDay, _period.endDay).days;

			drawDates(period);

			if (_percents)
				removeChild(_percents);
			_percents = addChild(new Sprite()) as Sprite;
			_percents.mouseEnabled = false;

			if (_indexes)
				removeChild(_indexes);
			_indexes = addChild(new Sprite()) as Sprite;
			_indexes.mouseEnabled = false;
			_indexes.x = _width;

			var min : Number = period.minIndex;
			var max : Number = period.maxIndex;

			var overscale : Number = (max - min) * 0.05;
			min -= overscale;
			max += overscale;

			var posY : Number;
			var tf : TextField;
			for (var i : int = 0; i < 10; i++) {
				posY = _height / 10 * i;

				tf = new TextField();
				tf.defaultTextFormat = getStyleForPercent();
				tf.text = (100 - i * 10) + "%";
				tf.multiline = false;
				tf.selectable = false;
				tf.autoSize = TextFieldAutoSize.LEFT;
				tf.x -= tf.textWidth + 5;
				tf.y = posY - tf.textHeight / 1.6;
				_percents.addChild(tf);

				tf = new TextField();
				tf.defaultTextFormat = getStyleForIndex();
				tf.text = formatIndexValue((max - ((max - min) / 10) * i));
				tf.multiline = false;
				tf.selectable = false;
				tf.autoSize = TextFieldAutoSize.LEFT;
				tf.x = 4;
				tf.y = posY - tf.textHeight / 1.6;
				_indexes.addChild(tf);
			}
		}

		private function drawDates(period : PeriodData) : void {
			
			var pts : TimeSpan = TimeSpan.fromDates(period.startDay, period.endDay);
			var slots : int = Math.floor(_width / GRIDWIDTH);

			var years : int = Math.floor(pts.days / 365);
			var months : int = Math.floor(pts.days / 30.5);

			var selection : uint = 0;
			if (Math.abs(1 - (slots / months)) < Math.abs(1 - (slots / pts.days)) && months > 0)
				selection = 1;
			if (Math.abs(1 - (slots / years)) < Math.abs(1 - (slots / months)) && years > 0)
				selection = 2;

			if (_dates)
				removeChild(_dates);

			_dates = addChild(new Sprite()) as Sprite;
			_dates.graphics.lineStyle(0, Configuration.getInstance().strongColor);
			_dates.mouseEnabled = false;

			switch(selection) {
				case 0:
					drawDays(period,pts.days);
					break;
				case 1:
					drawMonth(period,months);
					break;
				case 2:
					drawYears(period);
					break;
			}
		}

		private function drawYears(period : PeriodData) : void {
			
			var currentYear : int = period.startDay.fullYearUTC;
			var beginOffset : Number = period.startDay.valueOf();
			var gridDate : Date = new Date(currentYear, 0, 1);
			currentYear++;

			while (currentYear <= period.endDay.fullYear) {
				gridDate.fullYear = currentYear;
				var yearx : Number = getXforDay((gridDate.valueOf() - beginOffset) / TimeSpan.MILLISECONDS_IN_DAY);
				_dates.graphics.moveTo(yearx, _height);
				_dates.graphics.lineTo(yearx, 0);
				attachDateField(yearx, currentYear.toString());
				currentYear++;
			}
		}
		
		private function drawMonth(period : PeriodData, magnifier: Number) : void {
			
			var slots : int = Math.floor(_width / GRIDWIDTH);
			var step: int = magnifier>slots ? Math.round(magnifier/slots) : 1; 
			
			var currentYear : int = period.startDay.fullYearUTC;
			var currentMonth : int = period.startDay.month;
			var beginOffset : Number = period.startDay.valueOf();
			var gridDate : Date = new Date(currentYear, currentMonth, 1);
			gridDate = increseMonth(gridDate);
			var yearX: Number = 0;

			while (yearX < _width) {
				yearX = getXforDay((gridDate.valueOf() - beginOffset) / TimeSpan.MILLISECONDS_IN_DAY);
				_dates.graphics.moveTo(yearX, _height);
				_dates.graphics.lineTo(yearX, 0);
				attachDateField(yearX, getMonthAsLatin(gridDate.month)+"."+String(gridDate.fullYear));
				gridDate = increseMonth(gridDate,step);
			}
		}
		
		private function drawDays(period : PeriodData, magnifier: Number) : void {
			
			var slots : int = Math.floor(_width / GRIDWIDTH);
			var step: int = magnifier>slots ? Math.round(magnifier/slots) : 1; 
			
			var currentYear : int = period.startDay.fullYearUTC;
			var currentMonth : int = period.startDay.month;
			var currentDay : int = period.startDay.date;
			
			var beginOffset : Number = period.startDay.valueOf();
			var gridDate : Date = new Date(currentYear, currentMonth, currentDay);
			gridDate = increseDay(gridDate);
			var yearX: Number = 0;

			while (yearX < _width) {
				yearX = getXforDay((gridDate.valueOf() - beginOffset) / TimeSpan.MILLISECONDS_IN_DAY);
				_dates.graphics.moveTo(yearX, _height);
				_dates.graphics.lineTo(yearX, 0);
				attachDateField(yearX, String(gridDate.date)+"."+getMonthAsLatin(gridDate.month)+"."+String(gridDate.fullYear).substr(2,2));
				gridDate = increseDay(gridDate,step);
			}
		}
		
		private function increseMonth(date: Date, increseValue:int = 1):Date{
			
			date.month+=increseValue;
			return date;
			
		}
		
		private function increseDay(date: Date, increseValue:int = 1):Date{
			
			date.date+=increseValue;
			return date;
			
		}
		
		private function getMonthAsLatin(number: int): String {
			var array: Array = ['I','II','III','IV','V','VI','VII','VIII','IX','X','XI','XII'];
			return array[number];
			
		}

		private function attachDateField(at : Number, what : String) : void {
			
			var tf : TextField = new TextField();
			tf.defaultTextFormat = getStyleForData();
			tf.text = what;
			tf.multiline = false;
			tf.selectable = false;
			tf.autoSize = TextFieldAutoSize.LEFT;
			tf.x = at - tf.width/2;
			tf.y = _height;
			_dates.addChild(tf);
		}

		private function getXforDay(day : int) : Number {
			var step : Number = _width / _daysCount;
			return day * step;
		}

		private function formatIndexValue(value : Number) : String {
			var before : String = String(value);
			var out : String = before.split('.')[0];
			var end : String = before.split('.')[1];
			end = end.length == 1 ? "0" + end : end;
			end = end.length > 2 ? end.substr(0, 2) : end;
			return out + '.' + end;
		}

		private function getStyleForPercent() : TextFormat {
			var tf : TextFormat = new TextFormat();
			// tf.align = TextFormatAlign.RIGHT;
			tf.size = 9;
			tf.font = "Tahoma";
			tf.color = Configuration.getInstance().percentColor;
			return tf;
		}

		private function getStyleForIndex() : TextFormat {
			var tf : TextFormat = new TextFormat();
			// tf.align = TextFormatAlign.RIGHT;
			tf.size = 9;
			tf.font = "Tahoma";
			tf.color = Configuration.getInstance().indexColor;
			return tf;
		}

		private function getStyleForData() : TextFormat {
			var tf : TextFormat = new TextFormat();
			// tf.align = TextFormatAlign.CENTER;
			tf.size = 9;
			tf.font = "Tahoma";
			tf.color = Configuration.getInstance().lightColor;
			return tf;
		}
	}
}
